Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links

Superficie de Bézier, con Textura

En este caso a la superficie de Bezier le aplico una imagen como textura, la cual esta en formato .raw, ya que es muy facil leer este tipo de archivos. La definicion de las fuentes de luz, los materiales, y todo lo demas es similar al resto de los programas en OpenGL.

Los puntos de control de la superficie estan definidos en el arreglo ctrlpoints[5][5][3].

La textura es cargada en el arreglo ColorImagen[AnchoImagen][AltoImagen][3], donde AnchoImagen y AltoImagen son las dimensiones en pixels de la imagen, [3] representa las componentess Rojo, Verde, Azul.

Las coordenadas de la textura se definen en el arreglo texpts[2][2][2], segun que valor tome este arreglo, se puede repetir una o mas veces la textura.

texpts[2][2][2] = {{{0.0, 0.0}, 
{0.0, 1.0}},
{{1.0, 0.0}, 
{1.0, 1.0}}}
texpts[2][2][2] = {{{0.0, 0.0}, 
{0.0, 2.0}},
{{2.0, 0.0}, 
{2.0, 2.0}}}
texpts[2][2][2] = {{{0.0, 0.0}, 
{0.0, 3.0}},
{{3.0, 0.0}, 
{3.0, 3.0}}}

Esta instrucción define el Evaluator 2D de OpenGL, aqui se le especifica el número de puntos de control de la superficie, como asi tambien el arreglo donde estan definidos estos puntos. Con GL_MAP2_VERTEX_3 se le indica que se le van a pasar coordenadas de los vertices, de los puntos de control (x,y,z).

glMap2f(GL_MAP2_VERTEX_3, 
         0, 1, 3, 5,
         0, 1, 15, 5, 
         &ctrlpoints[0][0][0])

Activa el Evaluator.

glEnable(GL_MAP2_VERTEX_3)

Esta función me crea una grilla 2D, es usada con glMap2f() para evaluar eficientemente y crear la malla con las coordenadas de la superficie.

glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0)

Se define el Evaluator pero para las coordenadas de la textura (s,t), esto es asi por GL_MAP2_TEXTURE_COORD_2, ademas se le indica el arreglo donde estan estas texpts[][][].

glMap2f(GL_MAP2_TEXTURE_COORD_2, 
         0, 1, 2, 2,
         0, 1, 4, 2, 
         &texpts[0][0][0])

Me activa las coordenadas de mapeo para la textura.

glEnable(GL_MAP2_TEXTURE_COORD_2)

Para utilizar de textura una imagen en este caso,esta debe estar previamente en formato raw podemos utilizar el Photoshop para esto, con la opción de intercalar que ofrece justo antes de guardar la imagen en este formato. Este proceso guarda la imagen como una secuencia continua de Bits, donde se especifica el color de cada pixel por su componentes Rojo, Verde y Azul, por ese orden intercalado, esto facilita mucho la lectura del archivo. Muy Importante OpenGL exige que las dimensiones de la imagen en unidades de pixels(ancho y alto), sean de 2nx2m, donde n y m son numeros enteros (Ej: n=8, m=8, 28x28 = 256x256 pixels).

CargaImagen()

La especificación de la Textura se realiza con el siguiente comando :

glTexImage2D(GL_TEXTURE_2D, 0, 3, AnchoImagen, 
             AltoImagen, 0, GL_RGB, GL_UNSIGNED_BYTE, 
             &ColorImagen[0][0][0])

Estas dos instrucciones indican como deben ser filtrados los colores si no se produce una ajuste exacto entre los pixels de la textura y los pixels de la pantalla.

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

Esta instruccion le indica a OpenGL, mediante el parametro GL_DECAL, que se dibujara la textura teniendo en cuenta solo el color de la imagen.

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)

Finalmente la instruccion glEnable() activa el proceso de texturado.

glEnable(GL_TEXTURE_2D)
textura01.jpg Imagen de la Textura utilizada, sus dimenciones son 256x256 y tiene que estar en formato raw, para este caso en particular, ya que puede estar en formato bmp, jpg, pero el proceso de carga seria diferente.

Código Fuente

Código en VisualC++ Bezsurf.zip (4 Kb), no incluyo el archivo raw.

//Este programa dibuja una superficie de Bezier
//con la aplicacion de una Textura.
//Ramiro Alcocer
//valcoey@hotmail.com
//www.oocities.org/valcoey/index.html

#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>

//puntos de control de la superficie
GLfloat ctrlpoints[5][5][3] = {
{{-2.0, -2.0, 1.0}, 
{-1.0, -2.0, 0.0}, 
{0.0, -2.0, 0.0}, 
{1.0, -2.0, 0.0}, 
{2.0, -2.0, 1.0}}, 
{{-2.0, -1.0, 0.0}, 
{-1.0, -1.0, 0.25}, 
{0.0, -1.0, 1.0}, 
{1.0, -1.0, 0.5},
{2.0, -1.0, 0.0}}, 
{{-2.0, 0.0, -1.0}, 
{-1.0, 0.0, 0.0}, 
{0.0, 0.0, 1.5},
{1.0, 0.0, 0.0},
{2.0, 0.0, -1.0}}, 
{{-2.0, 1.0, 0.0}, 
{-1.0, 1.0, 0.75}, 
{0.0, 1.0, 2.0}, 
{1.0, 1.0, 0.0},
{2.0, 1.0, 0.0}},
{{-2.0, 2.0, 1.0}, 
{-1.0, 2.0, 0.0}, 
{0.0, 2.0, 0.0}, 
{1.0, 2.0, 0.0},
{2.0, 2.0, 1.0}}
};

//coordenadas de la textura
GLfloat texpts[2][2][2] = {{{0.0, 0.0}, {0.0, 1.0}},
              {{1.0, 0.0}, {1.0, 1.0}}};

//tamaño de la textura
#define AnchoImagen 256 		
#define AltoImagen 256 
GLubyte ColorImagen[AnchoImagen][AltoImagen][3];

//angulos de rotacion
GLfloat rotx = 0.0;
GLfloat roty = 0.0;
GLfloat rotz = 0.0;

//Para cargar una imagen en formato RAW
void CargaImagen(void)
{ 
 int i, j;
 FILE *file;

 file=fopen("imagen.RAW","rb");
 if (file==NULL)
        { printf("Error fichero\n"); exit(1); }
 for (i = 0; i < AnchoImagen; i++) {
     for (j = 0; j <AltoImagen ; j++) {
         fread(&ColorImagen[i][j], sizeof(char), 3*256*256, file);
         fclose(file);
         }
     }
}

//parametros de la fuente de luz y del material de la
//superficie
void initlights(void)
{
GLfloat ambient[] = {0.5, 0.5, 0.5, 1.0};
GLfloat position[] = {0.0, 0.0, 1.0, 0.0};

GLfloat mat_diffuse[] = {0.9, 0.9, 0.9, 1.0};
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess[] = {100.0};

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_POSITION, position);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}

//dibuja la superficie 
void display(void)
{
 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glMatrixMode( GL_MODELVIEW_MATRIX );
 glLoadIdentity();
 glPushMatrix();
 glTranslated(0.0, 0.0, -12.0);
 glRotatef(rotx, 1.0, 0.0, 0.0);
 glRotatef(roty, 0.0, 1.0, 0.0);
 glRotatef(rotz, 0.0, 0.0, 1.0);
 glEvalMesh2(GL_FILL, 0, 20, 0, 20);
 glPopMatrix();
 glFlush();
}

void init(void)
{
 glClearColor(0.05f, 0.2f, 0.4f, 1.0f);	
 glMap2f(GL_MAP2_VERTEX_3, 
         0, 1, 3, 5,
         0, 1, 15, 5, 
         &ctrlpoints[0][0][0]);
 glEnable(GL_MAP2_VERTEX_3);
 glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
 glMap2f(GL_MAP2_TEXTURE_COORD_2, 
         0, 1, 2, 2,
         0, 1, 4, 2, 
         &texpts[0][0][0]);
 glEnable(GL_MAP2_TEXTURE_COORD_2);
  
 //carga la textura
 CargaImagen();
 glEnable(GL_DEPTH_TEST);
 glTexImage2D(GL_TEXTURE_2D, 0, 3, AnchoImagen, 
              AltoImagen, 0, GL_RGB, GL_UNSIGNED_BYTE, 
              &ColorImagen[0][0][0]);
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 glEnable(GL_TEXTURE_2D);
}

void reshape(int w, int h)
{
 glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
 glMatrixMode (GL_PROJECTION);
 glLoadIdentity ();
 gluPerspective(30, (GLfloat) w/(GLfloat) h, 1.0, 50.0);
 glMatrixMode (GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{
 switch (key) {
   case 'x':
   case 'X':
      rotx = rotx - 10.0f;
      glutPostRedisplay();
      break;
   case 's':
   case 'S':
      rotx = rotx + 10.0f;
      glutPostRedisplay();
      break;
   case 'y':
   case 'Y':
      roty = roty + 10.0f;
      glutPostRedisplay();
      break;
   case 't':
   case 'T':
      roty = roty - 10.0f;
      glutPostRedisplay();
      break;
   case 'a':
   case 'A':
      rotz = rotz - 10.0f;
      glutPostRedisplay();
      break;
   case 'z':
   case 'Z':
      rotz = rotz + 10.0f;
      glutPostRedisplay();
      break;

   case 27:
      exit(0);
      break;
   }
}

int main(int argc, char** argv)
{
 glutInit(&argc, argv);
 glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
 glutInitWindowSize (300, 300);
 glutInitWindowPosition (100, 100);
 glutCreateWindow ("Superficie de Bezier con Textura");
 init ();
 glutReshapeFunc(reshape);
 glutKeyboardFunc(keyboard);
 glutDisplayFunc(display);
 glutMainLoop();
 return 0;
}


valcoey@hotmail.com

Ramiro Alcocer, 2001

Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links